/*****************************************************************
 Naicigam Engine v0.1

 File: VertexBuffer.inl
 Created: 01/03/08
*****************************************************************/

//----------------------------------------------------------------
template<class VertexFormat, unsigned int FVF>
VertexBuffer<VertexFormat,FVF>::VertexBuffer ()
:
m_pkVBO(NULL),
m_pkDev(NULL)
{

}
//----------------------------------------------------------------
template<class VertexFormat, unsigned int FVF>
VertexBuffer<VertexFormat,FVF>::~VertexBuffer ()
{
	/***/
}
//----------------------------------------------------------------
template<class VertexFormat, unsigned int FVF>
bool VertexBuffer<VertexFormat,FVF>::create(IDirect3DDevice9* pkDev, bool bDynamic)
{
	// TO-DO: magic numbers
	m_uiVBOSize = 450;
	m_uiFlush = 150;
	m_uiBase = 0;
	m_ePrimitiveType = D3DPT_TRIANGLESTRIP;
	m_pkVBO = NULL;
	m_pkDev = pkDev;

	// create the vertex buffer
	HRESULT hr = pkDev->CreateVertexBuffer(
						m_uiVBOSize * sizeof(VertexFormat),
						(bDynamic ? D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC : 0),
						FVF,
						D3DPOOL_DEFAULT, 
						&m_pkVBO,
						NULL
	);

	return (hr == D3D_OK);
}
//----------------------------------------------------------------
template<class VertexFormat, unsigned int FVF>
void VertexBuffer<VertexFormat,FVF>::bind() const
{
	HRESULT hr = m_pkDev->SetVertexShader(NULL);
	hr = m_pkDev->SetFVF(FVF);
	hr = m_pkDev->SetStreamSource(0, m_pkVBO, NULL, sizeof(VertexFormat));
}
//----------------------------------------------------------------
template<class VertexFormat, unsigned int FVF>
void VertexBuffer<VertexFormat,FVF>::draw(const VertexFormat* pkVertices, 
											D3DPRIMITIVETYPE ePrimitive, 
											unsigned int uiVertexCount)
{
	m_ePrimitiveType = ePrimitive;

	// check the VBO limit
	if(m_uiFlush < uiVertexCount)
		m_uiVertexToLock = m_uiFlush;
	else
		m_uiVertexToLock = uiVertexCount;
	
	// reset counter
	if(m_uiBase + m_uiVertexToLock > m_uiVBOSize)
		m_uiBase = 0;
	
	// lock the VBO
	void* pvVertices = NULL;
	HRESULT hr = m_pkVBO->Lock(
								m_uiBase * sizeof(VertexFormat),
								m_uiVertexToLock * sizeof(VertexFormat),
								(void**)(&pvVertices),
								m_uiBase ? D3DLOCK_NOOVERWRITE: D3DLOCK_DISCARD
	);

	unsigned int uiVertexProcNow = 0;

	while(m_uiVertexToLock > 0)
	{
		// copy the vertices
		memcpy(
			pvVertices, 
			&pkVertices[uiVertexProcNow], 
			sizeof(VertexFormat) * m_uiVertexToLock
		); 
		
		uiVertexProcNow += m_uiVertexToLock;

		// unlock the vertex buffer
		hr = m_pkVBO->Unlock();

		// flush all the vertices
		flush();

		// update the counters
		m_uiBase += m_uiVertexToLock;

		if(m_uiFlush < (uiVertexCount - uiVertexProcNow))
			m_uiVertexToLock = m_uiFlush;
		else
			m_uiVertexToLock = uiVertexCount - uiVertexProcNow;
		
		// reset the base
		if (m_uiBase + m_uiVertexToLock > m_uiVBOSize)
			m_uiBase = 0;

		// lock the VBO
		hr = m_pkVBO->Lock(
			m_uiBase * sizeof(VertexFormat),
			m_uiVertexToLock * sizeof(VertexFormat),
			(void**)(&pkVertices),
			m_uiBase ? D3DLOCK_NOOVERWRITE : D3DLOCK_DISCARD
		);
	}		

	// unlock the buffer
	m_pkVBO->Unlock();
}
//----------------------------------------------------------------
template<class VertexFormat, unsigned int FVF>
void VertexBuffer<VertexFormat,FVF>::flush()
{
	unsigned int uiPrimitiveCount = 0;

	// check the primitive type
	if (m_ePrimitiveType == D3DPT_TRIANGLELIST)
		uiPrimitiveCount = m_uiVertexToLock / 3;
	else if (m_ePrimitiveType == D3DPT_TRIANGLESTRIP)
		uiPrimitiveCount = m_uiVertexToLock - 2;
	else
	{
		assert(0);
	}

	HRESULT hr = m_pkDev->DrawPrimitive(m_ePrimitiveType, m_uiBase, uiPrimitiveCount);

	assert(hr == D3D_OK);
}
//----------------------------------------------------------------
template<class VertexFormat, unsigned int FVF>
void VertexBuffer<VertexFormat,FVF>::release(void)
{
	/***/
}
//----------------------------------------------------------------